package com.linkhub.oms.data.sync.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import com.linkhub.oms.admin.modules.order.domain.param.ManualCreateOrderParam;
import com.linkhub.oms.common.enums.IEnumConvert;
import com.linkhub.oms.common.enums.mp.*;
import com.linkhub.oms.common.util.OffSetDateTimeUtil;
import com.linkhub.oms.common.util.QtBeanUtil;
import com.linkhub.oms.common.util.QtOptionalUtil;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.data.sync.api.shopify.domain.response.ShopOrderResponse;
import com.linkhub.oms.data.sync.enums.OrderFinancialStatusEnum;
import com.linkhub.oms.entity.OrderAddressEntity;
import com.linkhub.oms.entity.OrderEntity;
import com.linkhub.oms.entity.OrderProductEntity;
import com.linkhub.oms.entity.innerproperties.OrderFulfillmentEntity;
import org.apache.commons.lang3.StringUtils;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * @Description: OrderAssist
 * @Author: echo
 * @Date: 2024/3/30 20:25
 * @Version: 1.0
 */
public class OrderAssist {


    public static OrderEntity convertNewOrder(String sysShopId,
                                              ShopOrderResponse.Orders order,
                                              boolean snowflakeId,
                                              Collection<Long> matchProductSkuIds) {


        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setSysShopId(sysShopId);
        orderEntity.setPlatFormOrderId(order.getId());

        String sysOrderId = String.format("%s%s", sysShopId, order.getOrderNumber());
        if (snowflakeId) {
            sysOrderId = IdUtil.getSnowflake().nextIdStr();
        }
        orderEntity.setSysOrderId(sysOrderId);
        orderEntity.setPlatFormOrderId(order.getId());

        convertOrderCommonFields(order, orderEntity);

        orderEntity.setCreatedTime(LocalDateTime.now());
        orderEntity.setUpdateTime(LocalDateTime.now());

        List<OrderProductEntity> orderLineItems = convertOrderLineItems(sysShopId, sysOrderId, order.getLineItems());
        orderEntity.setOrderLineItems(orderLineItems);

        OrderAddressEntity orderAddress = convertOrderAddress(sysOrderId, order.getShippingAddress());
        orderEntity.setOrderAddress(orderAddress);

        fillOrderState(orderEntity, matchProductSkuIds, false);

        return orderEntity;

    }

    public static OrderEntity convertUpdateOrder(ShopOrderResponse.Orders order,
                                                 OrderEntity oldOrder,
                                                 Collection<Long> matchProductSkuIds,
                                                 boolean localOrderProduct,
                                                 boolean localOrderAddress) {

        String sysOrderId = oldOrder.getSysOrderId();
        String sysShopId = oldOrder.getSysShopId();
        OrderEntity orderEntity = new OrderEntity();
        convertOrderCommonFields(order, orderEntity);
        orderEntity.setId(oldOrder.getId());
        // 重置物流方式、运费
        orderEntity.setChannelCode("");
        orderEntity.setEstimatedFreight(null);
        orderEntity.setRegistrationFreight(null);

        if (!localOrderProduct) {
            List<OrderProductEntity> orderLineItems = convertOrderLineItems(sysShopId, sysOrderId, order.getLineItems());
            orderEntity.setOrderLineItems(orderLineItems);
        }

        if (!localOrderAddress) {
            OrderAddressEntity orderAddress = convertOrderAddress(sysOrderId, order.getShippingAddress());
            orderEntity.setOrderAddress(orderAddress);
        }


        fillOrderState(orderEntity, matchProductSkuIds, localOrderProduct);

        CustomerBusinessStatusEnum afterCustomerBizStatus = orderEntity.getCustomerBusinessStatus();
        CustomerBusinessStatusEnum beforeCustomerBizStatus = oldOrder.getCustomerBusinessStatus();
            // 待匹配 -> 待付款/待审核
            // 待付款 -> 待审核

            // 待处理 -> 待审核 不可逆
            // 待审核 -> 待付款 不可逆
        if ((CustomerBusinessStatusEnum.DUE.equals(afterCustomerBizStatus)
                || CustomerBusinessStatusEnum.PENDING_CHECK.equals(afterCustomerBizStatus))
                && !(CustomerBusinessStatusEnum.TO_BE_MATCHED.equals(beforeCustomerBizStatus)
                || CustomerBusinessStatusEnum.DUE.equals(beforeCustomerBizStatus) )) {
            orderEntity.setCustomerBusinessStatus(null);

        }

        return orderEntity;
    }


    public static void fillOrderState(OrderEntity order, Collection<Long> matchProductSkuIds, boolean localProduct) {
        // 根据付款状态转换订单状态
        OrderFinancialStatusEnum financialStatusEnum = IEnumConvert.valueOf(order.getFinancialStatus(),
                OrderFinancialStatusEnum.class);
        if (Objects.isNull(financialStatusEnum)) {
            financialStatusEnum = OrderFinancialStatusEnum.PENDING;
        }
        order.setOrderStatus(financialStatusEnum.getOrderStatus());

        if (StringUtils.isNotBlank(order.getCancelledAt())) {
            order.setOrderStatus(OrderStatusEnum.CANCELLED);
        }
        // 已取消/已退款
        if (OrderStatusEnum.CANCELLED.equals(order.getOrderStatus())
                || OrderStatusEnum.REFUNDED.equals(order.getOrderStatus())) {
            order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.VOID);
            order.setEmployeeBusinessStatus(EmployeeBusinessStatusEnum.CANCELLED);
            return;
        }

        // 发货状态有值
        if (StringUtils.isNotBlank(order.getFulfillmentStatus())) {
            order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.NON_SHIPO_ORDERS);
            return;
        }

        if (localProduct) {
            return;
        }

        // 默认待匹配
        order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.TO_BE_MATCHED);
        List<Long> shopSkuIds = QtStreamUtil.map(order.getOrderLineItems(), OrderProductEntity::getShopSkuId);
        // 全匹配上
        if (CollUtil.isNotEmpty(shopSkuIds) && CollUtil.containsAll(matchProductSkuIds, shopSkuIds)) {
            if (Objects.equals(order.getOrderStatus(), OrderStatusEnum.UNPAID)) {
                order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.DUE);
            } else {
                order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.PENDING_CHECK);
            }
        }

    }

    public static void fillOrderCustomerState(OrderEntity order) {
        if (Objects.equals(order.getOrderStatus(), OrderStatusEnum.UNPAID)) {
            order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.DUE);
        } else {
            order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.PENDING_CHECK);
        }
    }

    public static List<OrderProductEntity> convertOrderLineItems(String sysShopId,
                                                                 String sysOrderId,
                                                                 List<ShopOrderResponse.Orders.LineItems> lineItems) {

        return QtStreamUtil.map(lineItems, item -> convertOrderLineItem(sysShopId, sysOrderId, item));

    }

    public static OrderProductEntity convertOrderLineItem(String sysShopId, String sysOrderId, ShopOrderResponse.Orders.LineItems lineItem) {
        OrderProductEntity orderProduct = new OrderProductEntity();
        orderProduct.setSysOrderId(sysOrderId);
        orderProduct.setSysShopId(sysShopId);
        orderProduct.setShopProductId(lineItem.getProductId());
        orderProduct.setShopSkuId(lineItem.getVariantId());
        orderProduct.setSkuTitle(lineItem.getSku());
        orderProduct.setPrice(lineItem.getPriceSet().getShopMoney().getAmount());
        orderProduct.setCurrencyCode(lineItem.getPriceSet().getShopMoney().getCurrencyCode());
        orderProduct.setCurrentQuantity(lineItem.getCurrentQuantity());
        orderProduct.setProductType(OrderProductTypeEnum.THIRD_PARTY);
        orderProduct.setCreatedTime(LocalDateTime.now());
        orderProduct.setUpdateTime(LocalDateTime.now());

        return orderProduct;

    }


    public static OrderAddressEntity convertOrderAddress(String sysOrderId, ShopOrderResponse.Orders.ShippingAddress shippingAddress) {
        OrderAddressEntity orderAddress = new OrderAddressEntity();
        orderAddress.setSysOrderId(sysOrderId);
        QtBeanUtil.copyProperties(shippingAddress, orderAddress);
        orderAddress.setUpdateFlag(BoolEnum.NO);
        orderAddress.setCreatedTime(LocalDateTime.now());
        orderAddress.setUpdateTime(LocalDateTime.now());

        return orderAddress;


    }

    private static void convertOrderCommonFields(ShopOrderResponse.Orders order, OrderEntity orderEntity) {
        List<OrderFulfillmentEntity> orderFulfillmentList = QtBeanUtil.copyList(order.getFulfillments(), OrderFulfillmentEntity::new);
        orderEntity.setFulfillments(orderFulfillmentList);

        List<String> shipTitles = QtStreamUtil.map(order.getShippingLines(), ShopOrderResponse.Orders.ShippingLines::getTitle);
        QtOptionalUtil.of(shipTitles)
                .map(list -> list.get(0))
                .ifPresent(orderEntity::setShippingMethod);
        orderEntity.setCurrency(order.getCurrency());
        orderEntity.setOrderNumber(String.valueOf(order.getOrderNumber()));
        orderEntity.setEmail(order.getEmail());
        orderEntity.setCurrentTotalPrice(order.getCurrentTotalPrice());
        orderEntity.setFinancialStatus(order.getFinancialStatus());
        orderEntity.setFulfillmentStatus(order.getFulfillmentStatus());
        orderEntity.setBuyerNote(order.getNote());
        orderEntity.setCreatedAt(order.getCreatedAt());
        orderEntity.setCreatedAtConvert(OffSetDateTimeUtil.convertISO8601ToUTCDateTime(order.getCreatedAt()));
        orderEntity.setProcessedAt(order.getProcessedAt());
        orderEntity.setUpdatedAt(order.getUpdatedAt());
        orderEntity.setUpdatedAtConvert(OffSetDateTimeUtil.convertISO8601ToUTCDateTime(order.getUpdatedAt()));
        orderEntity.setCancelledAt(order.getCancelledAt());
        orderEntity.setDataStatus(DataStatusEnum.ENABLE);
    }

    // 构造手动订单对象
    public static OrderEntity ConvertManualOrder(String sysShopId, Collection<Long> matchProductSkuIds, ManualCreateOrderParam manualCreateOrderParam) {
        // 订单主信息
        ManualCreateOrderParam.OrderInfo orderInfo = manualCreateOrderParam.getOrderInfo();

        OrderEntity orderEntity = new OrderEntity();
        QtBeanUtil.copyProperties(orderInfo, orderEntity);
        orderEntity.setPlatFormOrderId(IdUtil.getSnowflake().nextId());

        String sysOrderId = String.format("%s%s", sysShopId, manualCreateOrderParam.getOrderInfo().getOrderNumber());
        orderEntity.setSysOrderId(sysOrderId);

        convertManualOrderCommonFields(manualCreateOrderParam, orderEntity);

        orderEntity.setCreatedTime(LocalDateTime.now());
        orderEntity.setUpdateTime(LocalDateTime.now());

        List<OrderProductEntity> orderLineItems = convertManualOrderLineItems(sysShopId, sysOrderId, manualCreateOrderParam.getProductList());
        orderEntity.setOrderLineItems(orderLineItems);

        OrderAddressEntity orderAddress = convertManualOrderAddress(sysOrderId, manualCreateOrderParam.getAddressInfo());
        orderEntity.setOrderAddress(orderAddress);

        fillOrderState(orderEntity, matchProductSkuIds, false);

        return orderEntity;

    }

    private static void convertManualOrderCommonFields(ManualCreateOrderParam manualCreateOrderParam, OrderEntity orderEntity) {
        orderEntity.setCurrentTotalPrice(calculateCurrentTotalPrice(manualCreateOrderParam));
        orderEntity.setFinancialStatus(OrderFinancialStatusEnum.PAID.getStatus());

        orderEntity.setCreatedAt(OffSetDateTimeUtil.getFormattedTime(orderEntity.getCreatedAt()));
        orderEntity.setCreatedAtConvert(OffSetDateTimeUtil.convertISO8601ToUTCDateTime(orderEntity.getCreatedAt()));
        orderEntity.setProcessedAt(orderEntity.getCreatedAt());
        String nowTime = OffSetDateTimeUtil.getFormattedTime(null);
        orderEntity.setUpdatedAt(nowTime);
        orderEntity.setUpdatedAtConvert(OffSetDateTimeUtil.convertISO8601ToUTCDateTime(nowTime));
        orderEntity.setDataStatus(DataStatusEnum.ENABLE);
    }

    private static String calculateCurrentTotalPrice( ManualCreateOrderParam manualCreateOrderParam) {
        List<ManualCreateOrderParam.ProductInfo> productList = manualCreateOrderParam.getProductList();
        if (productList == null || productList.isEmpty()) {
            throw new IllegalArgumentException("Product list cannot be null or empty");
        }

        BigDecimal total = BigDecimal.ZERO;

        for (ManualCreateOrderParam.ProductInfo product : productList) {
            // Ensure price and currentQuantity are not null to avoid NullPointerException
            if (product.getPrice() != null && product.getCurrentQuantity() != null) {
                BigDecimal productTotal = product.getPrice().multiply(BigDecimal.valueOf(product.getCurrentQuantity()));
                total = total.add(productTotal);
            } else {
                throw new IllegalArgumentException("Price or currentQuantity cannot be null for any product");
            }
        }

        // 加上运费
        BigDecimal sellFreight = manualCreateOrderParam.getOrderInfo().getSellFreight();
        if (sellFreight != null) {
            total = total.add(sellFreight);
        }

        return total.setScale(2, RoundingMode.DOWN).toPlainString();
    }

    public static List<OrderProductEntity> convertManualOrderLineItems( String sysShopId,
                                                                        String sysOrderId,
                                                                        @NotEmpty(message = "productList cannot be empty") @Valid List<ManualCreateOrderParam.ProductInfo> lineItems) {

        return QtStreamUtil.map(lineItems, item -> convertManualOrderLineItem(sysShopId, sysOrderId, item));

    }

    public static OrderProductEntity convertManualOrderLineItem( String sysShopId, String sysOrderId, ManualCreateOrderParam.ProductInfo lineItem) {
        OrderProductEntity orderProduct = new OrderProductEntity();
        orderProduct.setSysOrderId(sysOrderId);
        orderProduct.setSysShopId(sysShopId);
        orderProduct.setShopProductId(lineItem.getShopProductId());
        orderProduct.setShopSkuId(lineItem.getShopSkuId());
        orderProduct.setPrice(lineItem.getPrice().toPlainString());
        orderProduct.setCurrencyCode(lineItem.getCurrencyCode());
        orderProduct.setCurrentQuantity(lineItem.getCurrentQuantity());
        orderProduct.setProductType(OrderProductTypeEnum.THIRD_PARTY);
        orderProduct.setCreatedTime(LocalDateTime.now());
        orderProduct.setUpdateTime(LocalDateTime.now());

        return orderProduct;
    }

    public static OrderAddressEntity convertManualOrderAddress( String sysOrderId, ManualCreateOrderParam.@Valid @NotNull(message = "addressInfo cannot be null") AddressInfo shippingAddress) {
        OrderAddressEntity orderAddress = new OrderAddressEntity();
        orderAddress.setSysOrderId(sysOrderId);
        QtBeanUtil.copyProperties(shippingAddress, orderAddress);
        orderAddress.setUpdateFlag(BoolEnum.NO);
        orderAddress.setCreatedTime(LocalDateTime.now());
        orderAddress.setUpdateTime(LocalDateTime.now());

        return orderAddress;


    }
}
